/*
 * NumeradorServiceService.cpp
 *
 *  Created on: Dec 12, 2013
 *      Author: m
 */

#include <iostream>
#include <fstream>
#include <rpc/rpc.h>            /* always needed */
#include "RoutingService.h"
#include "../common/Exception.h"
#include "../../IPC/Sequence.h"
#include "../../common/ArchivoIni.h"

namespace channel{

const char* RoutingService::getServerAddress()
{
    static std::string serverAddress;

    if ( serverAddress.empty() )
    {
        //Get the RPC server address from config file
    	MapaIni config = ArchivoIni::parsearComoIni("config.ini");

        serverAddress = config["routing_server"];

        if ( serverAddress == "" )
            throw Exception( "Server ERROR: Server address not found!" );
    }

    return serverAddress.c_str();
}

CLIENT* RoutingService::createClient()
{
	CLIENT* cl;

	//Create client "handle" used for calling MESSAGEPROG on the
	//server designated on the command line. We tell the RPC package
	//to use the "tcp" protocol when contacting the server.

	cl = clnt_create( getServerAddress(), ROUTINGPROG, ROUTINGVERS, "tcp" );

	//Couldn’t establish connection with server.
	//Print error message and die.
	if ( cl == NULL )
		throw Exception( clnt_spcreateerror( getServerAddress() ) );

	return cl;
}


void RoutingService::create()
{
	ipc::Sequence::create(ROUTING_SEQ_PATH,ROUTING_SEQ_KEY);
}

void RoutingService::destroy()
{
	ipc::Sequence::destroy(ROUTING_SEQ_PATH,ROUTING_SEQ_KEY);
	ArchivoTexto::borrarArchivo(ROUTING_HOST_AGENT_FILE);
	ArchivoTexto::borrarArchivo(ROUTING_BROKER_HOST_FILE);
	ArchivoTexto::borrarArchivo(ROUTING_BROKER_HOST_ID_FILE);
}

int RoutingService::registerAgent(std::string hostName, std::string agentName)
{
	CLIENT* cl = createClient();
	int* value;

	register_agent_params param;

	param.host_name = (char*)hostName.c_str();
	param.agent_name = (char*)agentName.c_str();

	value = registeragent_1( &param, cl );

	//An error occurred while calling the server.
	//Print error message and die.
	if ( value == NULL )
		throw Exception( clnt_sperror( cl, getServerAddress() ) );

	//Okay, we successfully called the remote procedure.
	if ( *value < 0 )
		throw Exception( "Routing ERROR: couldn’t get next value" );

	clnt_destroy( cl );

	return *value;
}

int RoutingService::unregisterAgent(std::string hostName, std::string agentName)
{
	CLIENT* cl = createClient();
	int* value;
	register_agent_params param;

	param.host_name = (char*)hostName.c_str();
	param.agent_name = (char*)agentName.c_str();

	value = unregisteragent_1( &param, cl );

	//An error occurred while calling the server.
	//Print error message and die.
	if ( value == NULL )
		throw Exception( clnt_sperror( cl, getServerAddress() ) );

	// Okay, we successfully called the remote procedure.

	// Server was unable to resolve the name
	if ( *value < 0 )
		throw Exception( "Routing ERROR: couldn’t get next value" );

	clnt_destroy( cl );

	return *value;
}

int RoutingService::registerHost(std::string brokerName, std::string hostName)
{
	CLIENT* cl = createClient();
	int* value;

	// Create params
	register_host_params param;

	param.broker_name = (char*)brokerName.c_str();
	param.host_name = (char*)hostName.c_str();

	// Call the remote procedure  on the server
	value = registerhost_1( &param, cl );

	//An error occurred while calling the server.
    //Print error message and die.
	if ( value == NULL )
		throw Exception( clnt_sperror( cl, getServerAddress() ) );

	//Okay, we successfully called the remote procedure.

	//Server was unable to resolve the name
	if ( *value < 0 )
		throw Exception( "Routing ERROR: couldn’t get next value" );

	clnt_destroy( cl );

	return *value;
}

int RoutingService::unregisterHost(std::string brokerName, std::string hostName)
{
	CLIENT* cl = createClient();
	int* value;

	// Create params
	register_host_params param;

	param.broker_name = (char*)brokerName.c_str();
	param.host_name = (char*)hostName.c_str();

	// Call the remote procedure  on the server
	value = unregisterhost_1( &param, cl );

	//An error occurred while calling the server.
    //Print error message and die.
	if ( value == NULL )
		throw Exception( clnt_sperror( cl, getServerAddress() ) );

	//Okay, we successfully called the remote procedure.

	//Server was unable to resolve the name
	if ( *value < 0 )
		throw Exception( "Routing ERROR: couldn’t get next value" );

	clnt_destroy( cl );

	return *value;
}

int RoutingService::getHostIdbyAgent(std::string brokerName, std::string agentName)
{
	CLIENT* cl = createClient();
	int* value;

	/*
	 * Call the remote procedure "resolve_1" on the server
	 */
	get_host_id_by_agent_params param;

	param.broker_name = (char*)brokerName.c_str();
	param.agent_name = (char*)agentName.c_str();

	value = gethostidbyagent_1( &param, cl );

	//An error occurred while calling the server.
    //Print error message and die.
	if ( value == NULL )
		throw Exception( clnt_sperror( cl, getServerAddress() ) );

	//Okay, we successfully called the remote procedure.

	//Server was unable to resolve the name
	if ( *value < 0 )
		throw Exception( "Routing ERROR: couldn’t get next value" );

	clnt_destroy( cl );

	return *value;
}

int RoutingService::getHostIdbyHost(std::string brokerName, std::string hostName)
{
	CLIENT* cl = createClient();
	int* value;

	/*
	 * Call the remote procedure "resolve_1" on the server
	 */
	register_host_params param;

	param.broker_name = (char*)brokerName.c_str();
	param.host_name = (char*)hostName.c_str();

	value = gethostid_1( &param, cl );

	//An error occurred while calling the server.
    //Print error message and die.
	if ( value == NULL )
		throw Exception( clnt_sperror( cl, getServerAddress() ) );

	//Okay, we successfully called the remote procedure.

	//Server was unable to resolve the name
	if ( *value < 0 )
		throw Exception( "Routing ERROR: couldn’t get next value" );

	clnt_destroy( cl );

	return *value;
}

} //End namespace channel
